メッセージフォーマット - Noise Protocol Framework (3)
Noiseのメッセージは65535バイト以下であることが定められています。
これには以下の理由があるとのことです。
1. プロトコルの検証がやりやすい
2. 整数値のオーバーフローやメモリ領域に関するバグの可能性が減少する
3. Noiseプロトコルを利用するアプリケーションで定める上位プロトコルで、16ビットのメッセージ長を表すフィールドを用意することができるようになる
4. 大きなデータストリームのストリーミング復号化とランダムアクセス復号化のサポートを有効にする
正直、最後のやつについては理解できていませんが、それ以外については特に問題ないかと思います。
3番目のやつについては、メッセージの長さが16ビットの整数で表されるため、アプリケーションでメッセージをパースする際にどの範囲までパースすべきかを簡単に指定することができる、という意味かと思います。
Noiseプロトコルにはメッセージの型や長さを表す概念、フィールドは用意されていません。(必要であれば)上位プロトコルで定義することになります。
Noiseプロトコルには2種類のメッセージ(トランスポートメッセージ、ハンドシェイクメッセージ)が存在します。
トランスポートメッセージ
トランスポートメッセージはAEAD暗号文に16バイトの認証データを付与して(65535バイト以下で)構成します。
16バイトの認証データは、利用する暗号方式( AES256-GCM, ChaCha20Poly1305など)によって異なります。
ハンドシェイクメッセージ
ハンドシェイクメッセージも65535バイト以下です。メッセージは鍵合意で必要な(1つ以上の)公開鍵から始まります。
それに続けて、証明書や他の認証データなどのような任意のデータを含めることができます。もちろん、空の文字列でもよいです。
静的な公開鍵とペイロードは、DH鍵合意される前のハンドシェイクで送信された場合は平文で送信され、DH鍵合意が行われたあとの場合はAEAD暗号文で送信されます。トランスポートメッセージと同様に、AEAD暗号文は認証データのために16バイトだけ拡張されます。
例として、以下のハンドシェイクメッセージを考えます。
-> e
<- e, ee, s, es
-> s, se
最初のメッセージ(-> e)は平文の一時公開鍵"e"とそれに続く平文のペイロードで構成されます。
2番目のメッセージ( <- e, ee, s, es )は平文の一時公開鍵"e"、暗号化された静的公開鍵"s"、暗号化されたペイロードで構成されます。
3番目のメッセージ(-> s, se )は暗号化された静的公開鍵"s"と暗号化されたペイロードで構成されます。
各ペイロードが長さ0の文字列で、DH公開鍵が56バイトであると仮定すると、メッセージサイズは次のようになります。
(DH鍵の長さは利用する公開鍵暗号方式によって異なります)
最初のメッセージ(->e) ... 56 バイト
平文の公開鍵(56)
平文のペイロード(0)
2番目のメッセージ(<- e, ee, s, es) ... 144 バイト
平文の公開鍵(56)
暗号化された公開鍵(56 + 16)
暗号化されたペイロード(0 + 16)
3番目のメッセージ(-> s, se) ... 88 bytes
暗号化された公開鍵(56 + 16)
暗号化されたペイロード(0 + 16)